import sqlalchemy
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import Table
import Configuration
from Configuration import ACCOUNT_NUM, SEED_NUM, SEED_FOLLOWEE_NUM
from pymysql.err import OperationalError

Base = declarative_base()

ENGINE_INFO = 'mysql+pymysql://' + Configuration.DB_USER + ':' + Configuration.DB_PASSWD + '@' + Configuration.DB_HOST \
              + '/' + Configuration.DB_DATABASE + '?charset=' + Configuration.DB_CHARSET
ENGINE = sqlalchemy.create_engine(ENGINE_INFO)


class WeiboAccount(object):
    def __init__(self, email, password):
        self.email = email
        self.password = password


class Database(object):
    def __init__(self):
        self.engine = ENGINE
        self.connection = None
        self.session = None

    def connect(self):
        self.connection = self.engine.connect()
        session = sessionmaker(bind=self.engine, autocommit=False)
        self.session = session()

    def close(self):
        while True:
            try:
                self.session.commit()
                self.session.close()
                self.connection.close()
                break
            except OperationalError as oe:
                print oe



class SeedFollowee(Base):
    __table__ = Table(Configuration.DB_TABLES['seed_followee'], Base.metadata, autoload=True, autoload_with=ENGINE)

    def __init__(self, l):
        for key, value in l.items():
            setattr(self, key, value)

    @classmethod
    def reset_seed_fees(cls, seed_fees):
        db = Database()
        db.connect()

        for sf in seed_fees:
            cursor = db.session.query(cls).filter(cls.uid == sf).all()
            for cur in cursor:
                cur.is_available = '1'

        db.close()

    @classmethod
    def mark(cls, seed_fees):
        db = Database()
        db.connect()

        for sf in seed_fees:
            cursor = db.session.query(cls).filter(cls.uid == sf).all()
            for cur in cursor:
                cur.is_checked = '1'

        db.close()

    @classmethod
    def get_seed_followees(cls):
        db = Database()
        db.connect()

        cursor = db.session.query(cls).filter(cls.is_available == '1', cls.is_checked == '0').limit(SEED_FOLLOWEE_NUM)
        seed_followees = []
        for cur in cursor:
            cur.is_available = '0'
            uid = cur.uid
            if uid not in seed_followees:
                seed_followees.append(uid)

        db.close()

        return seed_followees


class Account(Base):
    __table__ = Table(Configuration.DB_TABLES['account'], Base.metadata, autoload=True, autoload_with=ENGINE)

    def __init__(self, l):
        for key, value in l.items():
            setattr(self, key, value)

    @classmethod
    def reset_accounts(cls, accounts):
        db = Database()
        db.connect()

        for acc in accounts:
            cursor = db.session.query(cls).filter(cls.email == acc.email).one()
            cursor.is_available = '1'

        db.close()

    @classmethod
    def ban_account(cls, email):
        """
        Ban the account with this email.
        :param email:
        :return:
        """
        db = Database()
        db.connect()

        cursor = db.session.query(cls).filter(cls.email == email).one()
        cursor.is_available = '0'
        cursor.is_deleted = '1'

        db.close()

    @classmethod
    def reset(cls, email):
        db = Database()
        db.connect()

        cursor = db.session.query(cls).filter(cls.email == email).one()
        cursor.is_available = '1'

        db.close()

    @classmethod
    def get_accounts(cls):
        """

        :return: a list of Account obj
        """
        db = Database()
        db.connect()

        cursor = db.session.query(cls).filter(cls.is_available == '1', cls.is_deleted == '0').limit(ACCOUNT_NUM)
        accounts = []
        for cur in cursor:
            cur.is_available = '0'
            accounts.append(WeiboAccount(cur.email, cur.password))

        db.close()

        return accounts


class Seed(Base):
    __table__ = Table(Configuration.DB_TABLES['seed'], Base.metadata, autoload=True, autoload_with=ENGINE)

    def __init__(self, l):
        for key, value in l.items():
            setattr(self, key, value)

    @classmethod
    def reset_seeds(cls, seeds):
        db = Database()
        db.connect()

        for sd in seeds:
            cursor = db.session.query(cls).filter(cls.uid == sd).one()
            cursor.is_available = '1'

        db.close()

    @classmethod
    def get_seeds(cls):
        """

        :return: a list of seed uids
        """
        db = Database()
        db.connect()

        cursor = db.session.query(cls).filter(cls.is_available == '1', cls.is_deleted == '0').limit(SEED_NUM)
        seeds = []
        for cur in cursor:
            cur.is_available = '0'
            seeds.append(cur.uid)

        db.close()

        return seeds


class ResultUser(Base):
    __table__ = Table(Configuration.DB_TABLES['result_user'], Base.metadata, autoload=True, autoload_with=ENGINE)

    def __init__(self, l):
        for key, value in l.items():
            setattr(self, key, value)



